#ifndef _NODE_H_
#define _NODE_H_

#include "../define/define.h"
#include "./speed.h"
#include "./controller.h"
#include "./packet_lost.h"
#include "../usocket/udpserver.h"
#include "../util/netstm.h"
#include "../main/protocol.h"
#include "../util/log.h"
#include "../util/lock.h"
#include "../util/timer.h"

#define default_node  128
#define default_packet_size 1024

struct data_node
{
	uint32 active; 
	uint32 time_out;
	
	uint32 req_tick;
	uint32 date_id;

	char*  buf[default_packet_size];
	uint32 buf_size;
};

class  Node_info
{
public:
	Node_info(uint32 con_id,ip_node node,UDPServer* udp,uint32 socket,uint32 d_socket,uint8 cmd)
	{
		m_log = new logfile("Node_info");
		m_con_id = con_id;
		m_ipnode     = node;
		m_s_socket   = socket;
		m_udp        = udp;
		m_con_tick   = 100;
		m_delay      = 30;
		m_last_tick  = 0;
		m_d_socket   = d_socket;
		m_pdu  = cmd;
		m_pack_count = 8;

	};

	~Node_info()
	{
	    delete m_log;
	};

	bool send_down_err(uint32 last_id)
	{
		char buf[1500] = {0};
		ByteStream ctrl((uint8*)buf,0,1024);
		ctrl << G_Ver;
		ctrl << DATA_down_error;
		ctrl << m_ipnode.count;
		ctrl << m_ipnode.l_port;
		ctrl << m_ipnode.d_ip;
		ctrl << m_ipnode.d_port;
		ctrl << m_con_id;
		ctrl << m_s_socket;
		ctrl << m_d_socket;
		uint32 ip_id = 1;
		ctrl << ip_id;
		ctrl << m_ipnode.trans_link[m_con_id].count;
		for(uint32 j =0; j<m_ipnode.trans_link[m_con_id].count; j++ )
				ctrl << m_ipnode.trans_link[m_con_id].trans_ip[j];
		ctrl << last_id;

		for(int j=0;j<3;j++)
		{
		  m_udp->sendbuf(m_ipnode.trans_link[m_con_id].trans_ip[1],
			 G_Port,buf,ctrl.Tell());
		
			char ttl[1023]= {0};
			in_addr s_ip; 
			memcpy(&s_ip,&m_ipnode.trans_link[m_con_id].trans_ip[0],sizeof(uint32));
			sprintf(ttl,"cmd=%d,socket=%d,last_id=%d,d_socket=%d,ip_id=%d,tell=%d,next_ip=%s,time=%d",
				DATA_down_error,m_s_socket,last_id,m_d_socket,ip_id,ctrl.Tell(),inet_ntoa(s_ip),get_time());
			m_log->WriteTrace(ttl);
		}
	
		return true;
	}

	bool send_down_over()
	{
		char buf[1500] = {0};
		ByteStream ctrl((uint8*)buf,0,1024);
		ctrl << G_Ver;
		ctrl << DATA_down_ok;
		ctrl << m_ipnode.count;
		ctrl << m_ipnode.l_port;
		ctrl << m_ipnode.d_ip;
		ctrl << m_ipnode.d_port;
		ctrl << m_con_id;
		ctrl << m_s_socket;
		ctrl << m_d_socket;
		uint32 ip_id = 1;
		ctrl << ip_id;
		ctrl << m_ipnode.trans_link[m_con_id].count;
		for(uint32 j =0; j<m_ipnode.trans_link[m_con_id].count; j++ )
				ctrl << m_ipnode.trans_link[m_con_id].trans_ip[j];


		for(int j=0;j<3;j++)
		m_udp->sendbuf(m_ipnode.trans_link[m_con_id].trans_ip[1],
			G_Port,buf,ctrl.Tell());
		
		char ttl[1023]= {0};
		in_addr s_ip; 
		memcpy(&s_ip,&m_ipnode.trans_link[m_con_id].trans_ip[0],sizeof(uint32));
		sprintf(ttl,"cmd=%d,socket=%d,d_socket=%d,ip_id=%d,tell=%d,next_ip=%s",
			DATA_down_ok,m_s_socket,m_d_socket,ip_id,ctrl.Tell(),inet_ntoa(s_ip));
		m_log->WriteTrace(ttl);	
		return true;
	}

    bool send_route()
	{
		char buf[1500] = {0};
		ByteStream ctrl((uint8*)buf,0,1024);
		ctrl << G_Ver;
		ctrl << DATA_route;
		ctrl << m_ipnode.count;
		ctrl << m_ipnode.l_port;
		ctrl << m_ipnode.d_ip;
		ctrl << m_ipnode.d_port;
		ctrl << m_con_id;
		ctrl << m_s_socket;
		ctrl << m_d_socket;
		uint32 ip_id = 1;
		ctrl << ip_id;
		for(uint32 i =0; i< m_ipnode.count; i++)
		{
			ctrl << m_ipnode.trans_link[i].count;
			for(uint32 j =0; j<m_ipnode.trans_link[i].count; j++ )
				    ctrl << m_ipnode.trans_link[i].trans_ip[j];
		}

		m_udp->sendbuf(m_ipnode.trans_link[m_con_id].trans_ip[1],
			G_Port,buf,ctrl.Tell());

		/*char ttl[1023]= {0};
		in_addr s_ip; 
		memcpy(&s_ip,&m_ipnode.trans_link[m_con_id].trans_ip[0],sizeof(uint32));
		sprintf(ttl,"cmd=%d,socket=%d,d_socket=%d,ip_id=%d,tell=%d,next_ip=%s",
			DATA_route,m_s_socket,m_d_socket,ip_id,ctrl.Tell(),inet_ntoa(s_ip));
		m_log->WriteTrace(ttl);*/

		return true;
	}


    bool send(data_node* pack,uint32 count)
	{
		m_lock.EnterLock();

		for(uint32 i=0; i<count; i++ )
		{
			char buf[1500] = {0};
			ByteStream ctrl((uint8*)buf,0,1024);
			ctrl << G_Ver;
			ctrl << m_pdu;
			ctrl << m_ipnode.count;
			ctrl << m_ipnode.l_port;
			ctrl << m_ipnode.d_ip;
			ctrl << m_ipnode.d_port;
			ctrl << m_con_id;
			ctrl << m_s_socket;
			ctrl << m_d_socket;
			uint32 ip_id = 1;
			ctrl << ip_id;
			ctrl << m_ipnode.trans_link[m_con_id].count;
			for(uint32 j =0; j<m_ipnode.trans_link[m_con_id].count; j++ )
				ctrl << m_ipnode.trans_link[m_con_id].trans_ip[j];

			ctrl << pack[i].date_id;
			ctrl << pack[i].buf_size;
			ctrl.Write(pack[i].buf,pack[i].buf_size);

			/*char tt[1023] = {0};
			in_addr ip; 
			memcpy(&ip,&m_ipnode.trans_link[m_con_id].trans_ip[1],sizeof(uint32));
			sprintf(tt,"send buf:cmd=%d,time=%d,m_s_socket=%d,con_id=%d,packet_count=%d,d_socket=%d,node_id=%d,m_con_id=%d,ip=%s,G_Port=%d,size=%d",
				m_pdu,get_time(),m_s_socket,m_con_id,m_pack_count,m_d_socket,pack[i].date_id,m_con_id,inet_ntoa(ip),
				G_Port,pack[i].buf_size);
			m_log->WriteTrace(tt);*/

			m_udp->sendbuf(m_ipnode.trans_link[m_con_id].trans_ip[1],
				G_Port,buf,ctrl.Tell());
		}

	    m_lost.add_req_count(count,m_active_tick);
		m_lock.LeaveLock();
		return true;
	};

	bool ack_pack_list(uint32 time)
	{
		 m_con_tick = (120 * (m_active_tick - time)) / 100 ; 
		 m_lost.add_rpy_count(1,m_active_tick);
		 m_speed.addbyte(1024,m_active_tick);
	     return true;
	}
	
	uint16 get_down_count()
	{
		m_lock.EnterLock();
		
		if(m_active_tick - m_last_tick < m_delay)	
		{
			m_lock.LeaveLock();
			return 0;
		};

		m_last_tick = m_active_tick;

		uint16 packcount = m_pack_count;
		uint16 delay = m_delay;
	
		if(m_ctrl.run(m_active_tick,m_lost.get_rate(),&packcount,&delay) == false)
		{
			m_lock.LeaveLock();
			return packcount;
		}
	
		m_pack_count = packcount;
		m_delay = delay;	
	
		m_lock.LeaveLock();
		return packcount;
	};
	
    uint32 get_last_tick()
	{
		return m_last_tick;
	};

	void  add_tick(uint32 tick)
	{
		m_active_tick = tick;
	};

	uint32 ping_time()
	{
		return m_con_tick;
	};

	uint32 cale(uint32 number)
	{
		return number % default_node;
	}

	float get_speed()
	{
		return m_speed.get_speed();
	}

	bool set_d_socket(uint32 d_socket)
	{
		m_d_socket = d_socket; 
		return true;
	}

private:

    uint32     m_last_tick;
	uint32   m_con_tick;

	uint32   m_active_tick;
	uint32     m_con_id;

	uint32    m_delay;
	uint32     m_pack_count;

	lock       m_lock;
	logfile*  m_log;

    speed      m_speed;
	controller m_ctrl;
	
	packet_lost m_lost;
	UDPServer*  m_udp;
   
	ip_node  m_ipnode;
	uint32   m_s_socket;
   
	uint8    m_pdu;
	uint32   m_d_socket;
};

#endif